#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "codeeditor.h"
#include "findreplacedialog.h"
#include "CompilerSet.h"

#define cn QString::fromLocal8Bit

//MainWindow类，继承自QMainWindow类，是程序的主类，在后面的main函数中实例化。
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0); //构造函数

    int getLastWindowState();
    void openSpecifiedFile(QString fileName);
    CodeEditor* addEditorTab(QString fileName);

signals:
    void sendBuildOutput(QByteArray);

private:
    enum ProgramType{CProgram, CPPProgram};
    enum TargetType{EXE, DLL, LIB};

    //白色，灰色和黑色调色板
    QPalette lightPalette;
    QPalette grayPalette;
    QPalette darkPalette;

    QStringList codeFileSuffixList;

    int toolBarIconSize = 24; //工具栏图标的大小设定
    int lastWindowState = 0; //上次关闭程序时的窗口状态，默认是0,即Normal
    int treeItemHeight = 26;

    QToolBar *mainToolBar = nullptr;	//工具栏控件
    QTabWidget *mainTabWidget = nullptr;
    QTreeWidget *treeWidget = nullptr;
    QTabWidget *infoTabWidget = nullptr;
    QPlainTextEdit *outputInfoEdit = nullptr;
    QTableView *infoTableView = nullptr;
    QStandardItemModel *infoItemModel = nullptr;
    QTableView *searchTableView = nullptr;
    QStandardItemModel *searchItemModel = nullptr;
    QSplitter *hSplitter = nullptr;
    QSplitter *vSplitter = nullptr;

    QPixmap yesPixmap;

    FindReplaceDialog *findReplaceDialog=nullptr;

    QFont outputTextEditFont = QFont(QStringList{"consolas", "Microsoft Yahei"}, 11);

    QMenuBar *menuBar = nullptr;

    QMenu *fileMenu = nullptr;
    QMenu *editMenu = nullptr;
    QMenu *searchMenu = nullptr;
    QMenu *viewMenu = nullptr;
    QMenu *projectMenu = nullptr;
    QMenu *executeMenu = nullptr;
    QMenu *toolsMenu = nullptr;
    QMenu *aStyleMenu = nullptr;
    QMenu *windowMenu = nullptr;
    QMenu *helpMenu = nullptr;

    QList<QMenu*> menuList;
    QMenu *exportMenu;
    QMenu* historyMenu;
    QMenu *snippetMenu;
    QMenu *toolBarDockMenu;
    QMenu* colorThemeMenu;

    QAction *newAction;
    QAction *openAction;
    QAction *saveAction;
    QAction *saveAsAction;
    QAction *exportDocAction;
    QAction *exportHTMLAction;
    QAction *printAction;
    QAction *clearRecentAction;
    QAction *exitAction;

    QAction *undoAction;
    QAction *redoAction;
    QAction *cutAction;
    QAction *copyAction;
    QAction *copyAsHtmlAction;
    QAction *pasteAction;
    QAction *selectAllAction;
    QAction *deleteAction;
    QAction *indentAction;
    QAction *unindentAction;
    QAction *commentOnOffAction;

    QAction *toolBarAction;
    QAction *statusBarAction;

    QAction *newProjectAction;
    QAction *openProjectAction;
    QAction *makefileAction;
    QAction *clearTempFileAction;
    QAction *closeProjectAction;

    QAction *colorThemeOptionAction;

    QAction *compileAction;
    QAction *runAction;
    QAction *compileRunAction;
    QAction *buildDllAction;
    QAction *buildLibAction;
    QAction *debugAction;
    QAction *profileAction;

    QAction *compilerOptionsAction;
    QAction *editorOptionsAction;
    QAction *fileManagerAction;
    QAction *consoleWindowAction;
    QAction *calculatorAction;
    QAction *lineCountAction;

    QAction *formatFileAction;
    QAction *formatOptionsAction;

    QAction *findAction;
    QAction* findPreviousAction;
    QAction* findNextAction;
    QAction *replaceAction;
    QAction *gotoLineAction;
    QAction* zoomInAction;
    QAction* zoomOutAction;
    QAction* dockTopAction;
    QAction* dockBottomAction;
    QAction* dockLeftAction;
    QAction* dockRightAction;

    QAction* lightThemeAction;
    QAction* grayThemeAction;
    QAction* darkThemeAction;

    QAction *fullscreenAction;
    QAction *closeAllTabAction;

    QAction *manualAction;
    QAction *aboutAction;

    QAction *renameFileAction;
    QAction *removeFileAction;
    QAction *precompileAction;
    QAction *openExplorerAction;

    QAction *addExistingFileAction;
    QAction *addNewFileAction;
    QAction *addNewClassAction;
    QAction *renameProjectAction;
    QAction *projectInformationAction;

    QToolButton *snippetToolButton;

    QStatusBar *statusBar = nullptr; //定义主窗口底部显示的状态栏
    QLabel *lineLabel = nullptr; //定义一个标签用于添加到状态栏上显示信息
    QLabel *columnLabel = nullptr; //定义一个标签用于添加到状态栏上显示信息
    QLabel *selectedLabel = nullptr; //定义一个标签用于添加到状态栏上显示信息
    QLabel *linesLabel = nullptr; //定义一个标签用于添加到状态栏上显示信息
    QLabel *compileModeLabel = nullptr; //定义一个标签用于添加到状态栏上显示信息
    QLabel *encodingLabel = nullptr; //定义一个标签用于添加到状态栏上显示信息

    QLabel *label1 = nullptr;
    QLabel *label2 = nullptr;
    QLabel *label3 = nullptr;
    QLabel *label4 = nullptr;
    QLabel *label5 = nullptr;
    QLabel *label6 = nullptr;

    bool isAutoFormat = false;
    int encodingIndex = 0;
    QString compileMode;

    int infoTabCurrentIndex = 0;
    QList<int> splitterSmallSizes;
    QList<int> splitterBigSizes;

    QElapsedTimer elapsedTimer;
    QTimer compilingTimer;

    QLocalServer *server; 	//此server用来接收QLocalSocket发来的代码文件名

    QClipboard *clipboard = QApplication::clipboard();

    QString language;

    QString CMainString =
        "#include <stdio.h>\n\n"
        "int main(void)\n"
        "{\n"
        "	printf(\"hello, world!\");\n\n"
        "	return 0;\n"
        "}";

    QString CPPMainString =
        "#include <iostream>\n\n"
        "using namespace std;\n\n"
        "int main()\n"
        "{\n"
        "	cout<<\"Hello, World!\"<<endl;\n\n"
        "	return 0;\n"
        "}";

    QMenu *projectContextMenu=nullptr;
    QMenu *itemContextMenu=nullptr;

    void treeWidgetItemPressed(QTreeWidgetItem* item, int column);
    void closeProjectMenuClicked();
    void closeProject(QTreeWidgetItem * topLevelItem);
    void removeProjectFile();
    void addNewProjectFile();
    void addNewProjectClass();
    void addExistingFileToProject();
    void renameProjectFile();
    void renameProject();
    bool isCodeFileSuffix(QString fileName);
    void addSubItem(QTreeWidgetItem *topItem, QString fileName);
    void newFile();	//添加一个新tab page
    void openProjectMenuClicked();//通过文件选择Dialog打开文件
    void openFile();//通过文件选择Dialog打开文件
    void saveFileActionClicked();//保存文件
    void saveAsFileActionClicked();//保存文件
    void saveFile(CodeEditor *codeEditor);//保存文件
    void saveAsFile(CodeEditor *codeEditor);//通过saveDialog保存文件
    bool save(QString sourceStr, QString fileName);
    void updateRecentFileActionList(QString fileName);
    void exportFile();
    void print();
    void printText(QPrinter*);
    void find();
    void replace();
    void findPreviousNext();
    void gotoLineActionClicked();
    void gotoLine(QString fileName, int rowNum, int colNum, QString searchString, bool caseSensitive);
    void tabCloseRequested(int); //关闭一个tab页时的处理函数
    void compilerOptions(); //打开编译器配置选项对话框
    void editorOptions();
    void colorThemeOptions();
    void fileManager();
    void openCMD();
    void openCalculator();
    void lineCount();
    QString compile(QString fileName); //编译函数
    QString buildProject(QString projectName, QStringList fileNames, QString rcFile, QString precompileFile, ProgramType program, TargetType targetType);
    void runMenuClicked();
    void run(QString fileName);
    void compileRun(bool needRun); //编译并运行
    void buildRun();
    void debug(); //启动GDB调试
    void permanceAnalysis();
    void currentTabChanged(int);
    void documentCursorPositionChanged();
    void documentModificationChanged(bool);
    void insertRecentFileAction(QString);
    void recentFileActionClicked();
    QString compileThread(QString compiler, QStringList arguments, QString workingPath);
    QString buildThread(QString make, QStringList makeFile, QString workingPath);
    QString byteArrayToString(QByteArray byteArray);
    QString getUntitledName();
    void dragEnterEvent(QDragEnterEvent *e) override;	 //有文件被拖到当前窗口时处理函数
    void dropEvent(QDropEvent *event) override; //有文件被drop到当前窗口时处理函数
    void newLocalConnection();	//新本地连接成功时处理函数
    void undo();
    void redo();
    void cut();
    void undoAvailableChanged(bool yes);
    void redoAvailableChanged(bool yes);
    void copyAvailableChanged(bool yes);
    void selectionChanged();
    void copy();
    void copyAsHtml();
    void paste();
    void selectAll();
    void deleteSelection();
    void insertCMain();
    void insertCppMain();
    void insertCppQtMain();
    void indent();
    void unindent();
    void commentOnOff();
    void newProject();
    void clipboardDataChanged();
    void showErrorList(QString projectFileName, QString errorStr, int& compileErrorNum, int& linkErrorNum, int& warningNum, int& firstErrorRow, int& firstErrorCol, QString& firstErrorFile);
    void compilingProgress();
    void tableViewDoubleClicked(const QModelIndex &);
    void clearRecentActions();
    void formatFileActionClicked();
    void formatOptionActionClicked();
    void toolBarOnOff();
    void statusBarOnOff();
    void fullscreenOnOff();
    void manual();
    void zoom();
    void changeToolBarDock();
    void changeColorTheme();
    void toolBarDockMenuAboutToShow();
    void fileMenuAboutToShow();
    void clearTempFileActionClicked();
    void clearTempFiles(QStringList);
    void projectMenuAboutToShow();
    void projectContextMenuAboutToShow();
    void itemContextMenuAboutToShow();
    void infoTabCurrentChanged(int index);
    void changeMenuLanguage(QString language);
    void changeToLightTheme();
    void changeToGrayTheme();
    void changeToDarkTheme();
    bool programHasConsole(const QString & filename);
    void addPathsToEnv();
    void treeWidgetItemDoubleClicked(QTreeWidgetItem *item, int column);
    void openProject(QString fileName);
    void setupProject(QString projectFile, QStringList sourceList, QStringList precompileList, ProgramType programType, CompilerSet compilerSet, int fileEncodingIndex);
    void keyPressEvent(QKeyEvent *event) override;
    void openExplorer();
    void precompileOnOff();
    void projectInformation();
    bool closeAllTabs();
    void openMakefile();
    bool notEqualCompilerSet(CompilerSet, CompilerSet);
    QString readStringFromFile(QString fileName, bool&success);
    QStringList getDependentHeaders(QString sourceFile);
    void openedFilesOKButtonClicked();
    void projectOKButtonClicked();
    int  searchInFiles(QString searchString, QStringList files, bool caseSensitive, bool wholeWordsOnly);
    int  replaceInFiles(QString searchString, QString replaceString, QStringList files, bool caseSensitive, bool wholeWordsOnly);
    int getProjectTotalLinesNumber(QTreeWidgetItem* item);
    void buildOutputReadyRead(QByteArray);
    void appExit(); //退出程序
    void closeEvent(QCloseEvent *event) override;//窗口关闭的处理函数
};
#endif
